'''
Author: leonard
Date: 2025-01-09 19:41:40
LastEditTime: 2025-01-10 10:39:31
FilePath: /cbd/main.py
Description: 

Copyright (c) 2025 by CBD Technology CO., Ltd, All Rights Reserved. 
'''
import re
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from tkinter import *
from tkinter import ttk
import openpyxl.styles
import openpyxl
from openpyxl.styles import Alignment, Font, NamedStyle

def read_log_file(file_path):
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            return f.read()
    except Exception as e:
        print(f"读取文件时出错: {e}")
        return None

def parse_log_file(log_content):
    # 存储所有数据包
    data_packages = []
    current_package = None
    
    # 按行解析
    lines = log_content.split('\n')
    i = 0
    while i < len(lines):
        line = lines[i].strip()
        
        # 检查探测命令行
        if '[CMD]command_sg_probe_check' in line:
            # 提取坐标
            coords = re.findall(r'x:(\d+)\s+y:(\d+)\s+z:(\d+)', line)
            if coords:
                # 如果找到新的坐标，保存前一个包并创建新包
                if current_package:
                    data_packages.append(current_package)
                
                current_package = {
                    'x': int(coords[0][0]),
                    'y': int(coords[0][1]),
                    'z': int(coords[0][2]),
                    'pressure_data': []  # 存储压力值数据
                }
        
        # 检查压力值数据行
        elif current_package and re.match(r'^\d+\s+-?\d+$', line):
            index, value = map(int, line.split())
            current_package['pressure_data'].append({
                'index': index,  # 保持原始索引值
                'value': value
            })
            
        i += 1
    
    # 添加最后一个数据包
    if current_package:
        data_packages.append(current_package)
        
    return data_packages

def plot_scatter(data_packages):
    # 准备绘图数据
    x_coords = []
    y_coords = []
    pressure_values = []
    
    # 收集所有数据点
    for package in data_packages:
        x = package['x']
        y = package['y']
        for data in package['pressure_data']:
            x_coords.append(x)
            y_coords.append(y)
            pressure_values.append(data['value'])
    
    # 创建散点图
    plt.figure(figsize=(10, 8))
    scatter = plt.scatter(x_coords, y_coords, c=pressure_values, cmap='viridis', s=100)
    plt.colorbar(scatter, label='压力值')
    plt.xlabel('X坐标')
    plt.ylabel('Y坐标')
    plt.title('XY平面压力分布')
    plt.grid(True)
    
    # 保存图片
    plt.savefig('pressure_distribution.png', dpi=300, bbox_inches='tight')
    plt.show()

class DataRangeSelector:
    def __init__(self, index_value_data):
        self.data = pd.DataFrame(index_value_data)
        self.root = Tk()
        self.root.title("数据范围选择器")
        
        window_width = 300
        window_height = 200
        screen_width = self.root.winfo_screenwidth()
        screen_height = self.root.winfo_screenheight()
        x = (screen_width - window_width) // 2
        y = (screen_height - window_height) // 2
        self.root.geometry(f"{window_width}x{window_height}+{x}+{y}")

        Label(self.root, text="起始索引:").pack(pady=5)
        self.start_var = StringVar(value=str(self.data['index'].min()))
        self.start_entry = Entry(self.root, textvariable=self.start_var)
        self.start_entry.pack(pady=5)

        Label(self.root, text="结束索引:").pack(pady=5)
        self.end_var = StringVar(value=str(self.data['index'].max()))
        self.end_entry = Entry(self.root, textvariable=self.end_var)
        self.end_entry.pack(pady=5)

        Button(self.root, text="绘制", command=self.plot).pack(pady=10)
        Button(self.root, text="绘制全部", command=self.plot_all).pack(pady=5)
        Button(self.root, text="退出", command=self.root.quit).pack(pady=5)

    def plot_line(self, start_index=None, end_index=None):
        if start_index is not None and end_index is not None:
            plot_data = self.data[(self.data['index'] >= start_index) & 
                                (self.data['index'] <= end_index)]
        else:
            plot_data = self.data

        plt.figure(figsize=(12, 6))
        plt.plot(plot_data['index'], plot_data['value'], '-b', linewidth=1)
        plt.grid(True)
        plt.xlabel('索引')
        plt.ylabel('数值')
        plt.title(f'数据折线图 (索引范围: {plot_data["index"].min()} - {plot_data["index"].max()})')
        
        max_value = plot_data['value'].max()
        min_value = plot_data['value'].min()
        max_index = plot_data.loc[plot_data['value'].idxmax(), 'index']
        min_index = plot_data.loc[plot_data['value'].idxmin(), 'index']
        
        plt.annotate(f'最大值: {max_value}', 
                    xy=(max_index, max_value), 
                    xytext=(10, 10),
                    textcoords='offset points')
        plt.annotate(f'最小值: {min_value}', 
                    xy=(min_index, min_value), 
                    xytext=(10, -10),
                    textcoords='offset points')
        
        plt.show()

    def plot(self):
        try:
            start = int(self.start_var.get())
            end = int(self.end_var.get())
            if start > end:
                start, end = end, start
            self.plot_line(start, end)
        except ValueError:
            print("请输入有效的索引范围")

    def plot_all(self):
        self.plot_line()

    def run(self):
        self.root.mainloop()

def save_to_csv(data_packages, output_file='pressure_data.csv'):
    # 按x,y坐标分组
    grouped_packages = {}
    for package in data_packages:
        key = (package['x'], package['y'])
        if key not in grouped_packages:
            grouped_packages[key] = []
        grouped_packages[key].append(package)
    
    # 创建Excel写入器
    with pd.ExcelWriter(output_file.replace('.csv', '.xlsx'), engine='openpyxl') as writer:
        # 为每组相同x,y坐标创建一个工作表
        for idx, ((x, y), packages) in enumerate(grouped_packages.items()):
            # 准备数据
            all_data = []  # 存储所有压力值序列
            current_sequence = []  # 当前压力值序列
            
            # 收集并分组压力值数据
            for package in packages:
                for data in package['pressure_data']:
                    # 当遇到索引1时，开始新的序列
                    if data['index'] == 1 and current_sequence:
                        all_data.append(current_sequence)
                        current_sequence = []
                    current_sequence.append(data)
            
            # 添加最后一个序列
            if current_sequence:
                all_data.append(current_sequence)
            
            # 创建DataFrame
            max_rows = max(len(seq) for seq in all_data)
            df_data = {
                'x': [x] + [''] * (max_rows - 1),
                'y': [y] + [''] * (max_rows - 1)
            }
            
            # 为每个序列创建两列（索引和压力值）
            for i, sequence in enumerate(all_data, 1):
                index_col = f'index_{i}'
                value_col = f'pressure_value_{i}'
                df_data[index_col] = [data['index'] for data in sequence] + [''] * (max_rows - len(sequence))
                df_data[value_col] = [data['value'] for data in sequence] + [''] * (max_rows - len(sequence))
            
            # 转换为DataFrame
            df = pd.DataFrame(df_data)
            
            # 使用坐标值命名工作表
            sheet_name = f'x{x}y{y}'
            try:
                df.to_excel(writer, sheet_name=sheet_name, index=False)
            except Exception as e:
                sheet_name = f'{sheet_name}_{idx+1}'
                df.to_excel(writer, sheet_name=sheet_name, index=False)
            
            # 获取工作表
            worksheet = writer.sheets[sheet_name]
            
            # 设置列宽
            for col in worksheet.column_dimensions.keys():
                worksheet.column_dimensions[col].width = 15
            
            # 设置所有单元格居中对齐
            for row in worksheet.iter_rows():
                for cell in row:
                    cell.alignment = openpyxl.styles.Alignment(horizontal='center')
            
            # 合并坐标单元格（如果有多行数据）
            if max_rows > 1:
                for col in range(1, 3):  # x, y列
                    worksheet.merge_cells(
                        start_row=2,
                        start_column=col,
                        end_row=max_rows + 1,
                        end_column=col
                    )
            
            # 添加标题样式
            header_style = openpyxl.styles.NamedStyle(name=f'header_style_{idx}')
            header_style.font = openpyxl.styles.Font(bold=True)
            header_style.alignment = openpyxl.styles.Alignment(horizontal='center')
            
            for col in range(1, len(df.columns) + 1):
                cell = worksheet.cell(row=1, column=col)
                cell.style = header_style
    
    print(f"\nExcel文件已保存至: {output_file.replace('.csv', '.xlsx')}")

def save_filtered_data(data_packages, start_index=260, end_index=360, output_file='filtered_pressure_data.csv'):
    # 按x,y坐标分组
    grouped_packages = {}
    for package in data_packages:
        key = (package['x'], package['y'])
        if key not in grouped_packages:
            grouped_packages[key] = []
        grouped_packages[key].append(package)
    
    # 创建Excel写入器
    with pd.ExcelWriter(output_file.replace('.csv', '.xlsx'), engine='openpyxl') as writer:
        # 为每组相同x,y坐标创建一个工作表
        for idx, ((x, y), packages) in enumerate(grouped_packages.items()):
            # 准备数据
            all_data = []  # 存储所有压力值序列
            current_sequence = []  # 当前压力值序列
            new_index = 1  # 重新编号的索引值
            
            # 收集并过滤压力值数据
            for package in packages:
                for data in package['pressure_data']:
                    # 只保留指定索引范围内的数据
                    if start_index <= data['index'] <= end_index:
                        # 当遇到起始索引时，开始新的序列
                        if data['index'] == start_index and current_sequence:
                            all_data.append(current_sequence)
                            current_sequence = []
                            new_index = 1  # 重置索引值
                        # 创建新的数据点，使用新的索引值
                        current_sequence.append({
                            'index': new_index,
                            'value': data['value']
                        })
                        new_index += 1
            
            # 添加最后一个序列
            if current_sequence:
                all_data.append(current_sequence)
            
            # 如果没有符合条件的数据，跳过该坐标点
            if not all_data:
                continue
                
            # 创建DataFrame
            max_rows = max(len(seq) for seq in all_data)
            df_data = {
                'x': [x] + [''] * (max_rows - 1),
                'y': [y] + [''] * (max_rows - 1)
            }
            
            # 为每个序列创建两列（索引和压力值）
            for i, sequence in enumerate(all_data, 1):
                index_col = f'index_{i}'
                value_col = f'pressure_value_{i}'
                df_data[index_col] = [data['index'] for data in sequence] + [''] * (max_rows - len(sequence))
                df_data[value_col] = [data['value'] for data in sequence] + [''] * (max_rows - len(sequence))
            
            # 转换为DataFrame
            df = pd.DataFrame(df_data)
            
            # 使用坐标值命名工作表
            sheet_name = f'x{x}y{y}'
            try:
                df.to_excel(writer, sheet_name=sheet_name, index=False)
            except Exception as e:
                sheet_name = f'{sheet_name}_{idx+1}'
                df.to_excel(writer, sheet_name=sheet_name, index=False)
            
            # 获取工作表
            worksheet = writer.sheets[sheet_name]
            
            # 设置列宽
            for col in worksheet.column_dimensions.keys():
                worksheet.column_dimensions[col].width = 15
            
            # 设置所有单元格居中对齐
            for row in worksheet.iter_rows():
                for cell in row:
                    cell.alignment = openpyxl.styles.Alignment(horizontal='center')
            
            # 合并坐标单元格（如果有多行数据）
            if max_rows > 1:
                for col in range(1, 3):  # x, y列
                    worksheet.merge_cells(
                        start_row=2,
                        start_column=col,
                        end_row=max_rows + 1,
                        end_column=col
                    )
            
            # 添加标题样式
            header_style = openpyxl.styles.NamedStyle(name=f'header_style_filtered_{idx}')
            header_style.font = openpyxl.styles.Font(bold=True)
            header_style.alignment = openpyxl.styles.Alignment(horizontal='center')
            
            for col in range(1, len(df.columns) + 1):
                cell = worksheet.cell(row=1, column=col)
                cell.style = header_style
    
    print(f"\n过滤后的数据已保存至: {output_file.replace('.csv', '.xlsx')}")

def main(file_path):
    # 读取日志文件
    log_content = read_log_file(file_path)
    if not log_content:
        return
    
    # 解析数据
    data_packages = parse_log_file(log_content)
    
    # 打印数据包信息
    print("\n数据包信息:")
    for idx, package in enumerate(data_packages):
        print(f"\n数据包 {idx + 1}:")
        print(f"坐标: x={package['x']}, y={package['y']}, z={package['z']}")
        print("压力值数据:")
        for data in package['pressure_data']:
            print(f"索引: {data['index']}, 值: {data['value']}")
    
    # 保存完整数据到Excel文件
    save_to_csv(data_packages)
    
    # 保存过滤后的数据（索引值在260-360之间）
    save_filtered_data(data_packages, 260, 360, 'filtered_pressure_data.csv')
    
    # 绘制压力分布散点图
    plot_scatter(data_packages)
    
    # 打印统计信息
    print("\n统计信息:")
    print(f"总数据包数: {len(data_packages)}")
    total_pressure_points = sum(len(package['pressure_data']) for package in data_packages)
    print(f"总压力值测量点数: {total_pressure_points}")

if __name__ == "__main__":
    import sys
    if len(sys.argv) != 2:
        print("使用方法: python script.py <日志文件路径>")
        sys.exit(1)
    
    file_path = sys.argv[1]
    main(file_path)